/*
 * Author: vdaras
 */


#include "StateStack.h"

#include "State.h"
#include "EngineCore.h"
#include "ServiceLocator.h"
#include <assert.h>


StateStack::StateStack()
:
m_mustPop(false)
{
}


StateStack::~StateStack()
{
    while( m_states.size( ) > 0 )
    {
        m_states.top( )->Cleanup( );
        delete m_states.top( );
        m_states.pop( );
    }
}


/**
 * Pushes a State to the stack. IMPORTANT, the State object's lifetime is now
 * determined by the StateStack.
 *
 * @param toPush
 */

void StateStack::Push(State* toPush)
{
    if( !m_states.empty( ) )
        m_states.top( )->Pause( );

    m_states.push( toPush );
    
    //set the gui contents of the pushed state as the active gui contents
    EngineCore *engineCore = ServiceLocator< EngineCore >::GetService( );
    gui::Screen *gScreen = engineCore->GetGuiScreen( );
    gScreen->AddComponent( toPush->GuiContents( ), 0, 0 );
}


/**
 * Pops top State from the Stack.
 */

void StateStack::Pop()
{
    if( m_mustPop )
	m_mustPop = false;
    
    assert( !m_states.empty() );

    //clean last State
    m_states.top( )->Cleanup( );

    delete m_states.top( );

    m_states.pop( );

    EngineCore *engineCore = ServiceLocator< EngineCore >::GetService( );
    gui::Screen *gScreen = engineCore->GetGuiScreen( );
    
    gScreen->Clear( );
    
    if( m_states.empty() )
    {
        //resume previous State
        m_states.top( )->Resume( );
	
	//set the gui contents of the previous state as the active gui contents
        gScreen->AddComponent( m_states.top( )->GuiContents( ), 0, 0 );
    }
}


/**
 * Notify the StateStack that the top state must be popped when it's appropriate.
 */

void StateStack::SafePop()
{
    m_mustPop = true;
}


/**
 * @return a pointer to the State at the top of the Stack.
 */

State* StateStack::Top() const
{
    assert( !m_states.empty());

    return m_states.top( );
}


/**
 * @return Count of States in stack.
 */

unsigned StateStack::Size() const
{
    return m_states.size( );
}